/*
 * ...
 */

package com.ruoyi.project.payUtils.wx.sdkV3;

import com.ruoyi.project.utils.JsonUtils;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.payments.app.AppService;
import com.wechat.pay.java.service.payments.app.AppServiceExtension;
import com.wechat.pay.java.service.payments.app.model.Amount;
import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
import com.wechat.pay.java.service.payments.app.model.PrepayResponse;
import com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.app.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.transferbatch.TransferBatchService;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequest;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 挺好的 2023年02月18日 下午 15:18
 */
public class QuickStart {

    /**
     * 商户号
     */
    public static String merchantId = "1598338101";

    /**
     * 商户API私钥路径
     */
    public static String privateKeyPath = "D:\\workspace\\dev\\zlg_2\\src\\main\\resources\\cert\\apiclient_key_1598338101.pem";

    /**
     * 微信支付平台证书
     */
    private static final String wechatPayCertPath = "D:\\workspace\\dev\\zlg_2\\src\\main\\resources\\cert" + "\\wechatpay_2025_06_03_73365F0599B3241EB602604F8EACCCE1382F2B2B_1598338101.pem";

    /**
     * 商户证书序列号
     */
    public static String merchantSerialNumber = "7DFA6FDE5F50071FBC32DB032C0F99B992915E81";

    /**
     * 商户APIV3密钥
     */
    public static String apiV3key = "9742d0e2aeead4aecb97002f03341b75";

    public static final String appId = "wx58cd94250038dbdb";

    public static final String miniAppId = "wx7dedaad636ca78fe";

    public static final String openId = "oucdf5PNOQu4BnBpydCwzTtrUQCc";

    public static void main (String[] args) {


        transfer(openId, "", "123456781011010101", BigDecimal.valueOf(10D));

        //        appPayExtension();

        //        jsApiPayExtension();

        //        System.out.println(orderQuery("15-119742-1672293301385"));
        ;

        //        jsApiPay();

        //        appPayExtension();
    }

    // java -jar CertificateDownloader.jar -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath} -c ${wechatpayCertificateFilePath}

    /**
     * 转账
     *
     * @param openId
     * @param userName
     * @param withDrawId
     * @param amount
     */
    public static void transfer (String openId, String userName, String withDrawId, BigDecimal amount) {

        try {
            Long totalAmount = amount.setScale(0, RoundingMode.HALF_UP).longValue();

            RSAConfig config = new RSAConfig.Builder().merchantId(merchantId)
                    // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
                    .privateKeyFromPath(privateKeyPath).merchantSerialNumber(merchantSerialNumber)
                    .wechatPayCertificatesFromPath(wechatPayCertPath).build();

            TransferBatchService service = new TransferBatchService.Builder().config(config).build();

            InitiateBatchTransferRequest initiateBatchTransferRequest = new InitiateBatchTransferRequest();
            initiateBatchTransferRequest.setAppid(appId);
            initiateBatchTransferRequest.setOutBatchNo(withDrawId);
            initiateBatchTransferRequest.setBatchName("找零工提现");
            initiateBatchTransferRequest.setBatchRemark("找零工提现");
            initiateBatchTransferRequest.setTotalAmount(totalAmount);
            initiateBatchTransferRequest.setTotalNum(1);

            List <TransferDetailInput> transferDetailListList = new ArrayList <>();

            {
                TransferDetailInput transferDetailInput = new TransferDetailInput();

                transferDetailInput.setOutDetailNo("detail" + withDrawId);
                transferDetailInput.setTransferAmount(totalAmount);
                transferDetailInput.setTransferRemark("找零工提现");

                transferDetailInput.setOpenid(openId);

                // 规定 < 0.3元的时候，不允许填写收款用户姓名
                if (totalAmount <= 30) {
                    transferDetailInput.setUserName(null);
                } else {
                    transferDetailInput.setUserName(userName);
                }

                transferDetailListList.add(transferDetailInput);
            }

            initiateBatchTransferRequest.setTransferDetailList(transferDetailListList);

            InitiateBatchTransferResponse response = service.initiateBatchTransfer(initiateBatchTransferRequest);
            System.out.println(response);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 订单查询
     *
     * @param outTradeNo
     *         商户交易号（系统交易的编号）
     */
    public static String orderQuery (String outTradeNo) {

        try {
            RSAConfig config = new RSAConfig.Builder().merchantId(merchantId)
                    // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
                    .privateKeyFromPath(privateKeyPath).merchantSerialNumber(merchantSerialNumber)
                    .wechatPayCertificatesFromPath(wechatPayCertPath).build();


            AppServiceExtension service = new AppServiceExtension.Builder().config(config).build();

            QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
            queryRequest.setMchid(merchantId);
            queryRequest.setOutTradeNo(outTradeNo);

            Transaction result = service.queryOrderByOutTradeNo(queryRequest);

            if (!"SUCCESS".equals(result.getTradeState())) {
                return result.getTradeStateDesc();
            }
        } catch (Exception e) {
            return e.getMessage();
        }

        return "查询成功";
    }

    private static void jsApiPayExtension () {
        RSAConfig config = new RSAConfig.Builder().merchantId(merchantId)
                // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
                .privateKeyFromPath(privateKeyPath).merchantSerialNumber(merchantSerialNumber)
                .wechatPayCertificatesFromPath(wechatPayCertPath).build();

        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(config).build();

        try {

            com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();

            com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();

            amount.setTotal(100);

            request.setAmount(amount);

            request.setAppid(miniAppId);
            request.setMchid(merchantId);
            request.setDescription("测试商品标题");
            request.setNotifyUrl("https://notify_url");
            request.setOutTradeNo("out_trade_no_0111111101");
            Payer payer = new Payer();
            payer.setOpenid("oucdf5KZBb0iZtYf-sVPu0j4X9H0");
            request.setPayer(payer);

            com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(
                    request);

            System.out.println(response);

            System.out.println(JsonUtils.objectToJson(request));
        } catch (HttpException e) { // 发送HTTP请求失败
            // 调用e.getHttpRequest()获取请求打印日志或上报监控，更多方法见HttpException定义
        } catch (ServiceException e) { // 服务返回状态小于200或大于等于300，例如500
            // 调用e.getResponseBody()获取返回体打印日志或上报监控，更多方法见ServiceException定义
        } catch (MalformedMessageException e) { // 服务返回成功，返回体类型不合法，或者解析返回体失败
            // 调用e.getMessage()获取信息打印日志或上报监控，更多方法见MalformedMessageException定义
        }

    }

    private static void appPayExtension () {
        RSAConfig config = new RSAConfig.Builder().merchantId(merchantId)
                // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
                .privateKeyFromPath(privateKeyPath).merchantSerialNumber(merchantSerialNumber)
                .wechatPayCertificatesFromPath(wechatPayCertPath).build();

        AppServiceExtension service = new AppServiceExtension.Builder().config(config).build();

        try {

            PrepayRequest request = new PrepayRequest();
            request.setAppid(appId);
            request.setMchid(merchantId);
            request.setDescription("测试商品标题");
            request.setNotifyUrl("https://notify_url");
            request.setOutTradeNo("out_trade_n44444o_001");

            Amount amount = new Amount();
            amount.setTotal(100);
            request.setAmount(amount);

            PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);


            System.out.println(response);
        } catch (HttpException e) { // 发送HTTP请求失败
            // 调用e.getHttpRequest()获取请求打印日志或上报监控，更多方法见HttpException定义
        } catch (ServiceException e) { // 服务返回状态小于200或大于等于300，例如500
            // 调用e.getResponseBody()获取返回体打印日志或上报监控，更多方法见ServiceException定义
        } catch (MalformedMessageException e) { // 服务返回成功，返回体类型不合法，或者解析返回体失败
            // 调用e.getMessage()获取信息打印日志或上报监控，更多方法见MalformedMessageException定义
        }

    }


    private static void jsApiPay () {

        Config config = new RSAAutoCertificateConfig.Builder().merchantId(merchantId).privateKeyFromPath(privateKeyPath)
                .merchantSerialNumber(merchantSerialNumber).apiV3Key(apiV3key).build();

        JsapiService service = new JsapiService.Builder().config(config).build();

        com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();

        com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();

        amount.setTotal(100);

        request.setAmount(amount);

        request.setAppid(miniAppId);
        request.setMchid(merchantId);
        request.setDescription("测试商品标题");
        request.setNotifyUrl("https://notify_url");
        request.setOutTradeNo("out_trade_no_0111111101");
        Payer payer = new Payer();
        payer.setOpenid("oucdf5KZBb0iZtYf-sVPu0j4X9H0");
        request.setPayer(payer);

        com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse response = service.prepay(request);

        System.out.println(response.getPrepayId());

    }

    private static void appPay () {
        Config config = new RSAAutoCertificateConfig.Builder().merchantId(merchantId).privateKeyFromPath(privateKeyPath)
                .merchantSerialNumber(merchantSerialNumber).apiV3Key(apiV3key).build();

        AppService service = new AppService.Builder().config(config).build();

        PrepayRequest request = new PrepayRequest();
        request.setAppid(appId);
        request.setMchid(merchantId);
        request.setDescription("测试商品标题");
        request.setNotifyUrl("https://notify_url");
        request.setOutTradeNo("out_trade_no_001");

        Amount amount = new Amount();
        amount.setTotal(100);
        request.setAmount(amount);

        PrepayResponse response = service.prepay(request);

        System.out.println(response);
        System.out.println(response.getPrepayId());
    }

}
